
import java.io.*;
import javax.servlet.*;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.*;
import java.util.List;
import org.jdom.*;
import org.jdom.input.*;
import org.jdom.output.*;
import org.jdom.xpath.*;
import java.net.*;

@WebServlet(urlPatterns={"/servlet/RecipeServer/*"})
public class RecipeServer extends HttpServlet {
	
   private static final long serialVersionUID = 1L;
   private static final String _dataFilePath = "/Users/hansii/Dev/data/recipes.xml";
   private static final String _xsdFilePath = "/Users/hansii/Dev/data/recipes.xsd";
	
   public RecipeServer() {
      super();
   }
   
   @SuppressWarnings("unchecked")	
   public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
	   try {
       	   Document d = loadXML(_dataFilePath);
           if (d == null) {
              response.sendError(HttpServletResponse.SC_NOT_FOUND, "No recipes XML fil found"); // 404  	
           }

           String uri = request.getRequestURI(); // /webtek/servlet/RecipeServer/recipies/Zuppa           
           uri = uri.substring(uri.indexOf("RecipeServer")+12);
   		
           XPath xp;
           
           if (uri.equals("/recipes") || uri.equals("/recipes/")) 
              xp = XPath.newInstance("//rcp:recipe");
           else
              xp = XPath.newInstance("//rcp:recipe[rcp:title = '"+URLDecoder.decode(uri.substring(9), "UTF-8")+"']");
           
           xp.addNamespace("rcp", "http://www.brics.dk/ixwt/recipes");
           List<Element> list = xp.selectNodes(d);
           if (!list.isEmpty()) {
              XMLOutputter out = new XMLOutputter();
              out.output(list, response.getWriter());    
           }
           else
              response.sendError(HttpServletResponse.SC_NOT_FOUND, "No recipe found"); // 404
       }
       catch (JDOMException ex) {
           response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Internal error occured: " + ex.getMessage()); // 500
       }
   }
  
   private Document loadXML(String xmlPath) throws JDOMException, IOException {
		File file = new File(xmlPath);
		Document doc = null;
		if (file.exists()) {
			doc = new SAXBuilder().build(file);
		} 
		return doc;
   }
   
   private Document getInputRecipe(HttpServletRequest request) {
	   try {
		   SAXBuilder builder = new SAXBuilder();
		   builder.setValidation(true);
		   builder.setProperty("http://java.sun.com/xml/jaxp/properties/schemaLanguage", "http://www.w3.org/2001/XMLSchema");
		   builder.setProperty("http://java.sun.com/xml/jaxp/properties/schemaSource", _xsdFilePath);

		   return (Document)builder.build(request.getInputStream());
	   }
	   catch (IOException e) {
	   } 
	   catch (JDOMException e) {			
	   }
	   return null;
   }
    
   protected void doPut(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		try {
			Document inputdoc = getInputRecipe(request);          
            Document doc = loadXML(_dataFilePath);
            
            if (doc == null) {
               response.sendError(HttpServletResponse.SC_NOT_FOUND, "Failure loading datafile"); // 404
               return;
            }
             
            Attribute recipeid = (Attribute)XPath.selectSingleNode(inputdoc, "//rcp:recipe/@id");
            
            if (XPath.selectSingleNode(doc, "//rcp:recipe[@id='" + recipeid.getValue() + "']") != null) {
               response.sendError(HttpServletResponse.SC_BAD_REQUEST, "Recipe allready exists"); // 400
               return;
            }
             
            Element r1 = (Element)inputdoc.getRootElement().clone();
             
            if (doc.getRootElement().addContent(r1) != null) {
            	XMLOutputter xout = new XMLOutputter();
    			java.io.FileWriter writer = new java.io.FileWriter(_dataFilePath);
    			xout.output(doc, writer);
    			writer.flush();
    			writer.close();   
            }
            else {
            	response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Failure adding recipe"); // 500
                return;
            }
		} 
		catch (Exception e) {
			response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR , "Internal error occured: " + e.getMessage()); // 500
		}
	}
    
    public void doDelete(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
    	try {
    		Document inputdoc = getInputRecipe(request);            
    		Document doc = loadXML(_dataFilePath);

    		if (doc == null) {
    			response.sendError(HttpServletResponse.SC_NOT_FOUND, "Failure loading datafile"); // 404
    			return;
    		}

    		Attribute recipeid = (Attribute)XPath.selectSingleNode(inputdoc, "//rcp:recipe/@id");
    		Element recipe = (Element)XPath.selectSingleNode(doc, "//rcp:recipe[@id='" + recipeid.getValue() + "']");

    		if (recipe == null) {
    			response.sendError(HttpServletResponse.SC_NOT_FOUND , "Recipe don't exists"); // 404
    			return;
    		}

    		if (doc.getRootElement().removeContent(recipe)) {
    			XMLOutputter xout = new XMLOutputter();
        		java.io.FileWriter xwriter = new java.io.FileWriter(_dataFilePath);
        		xout.output(doc, xwriter);
        		xwriter.flush();
        		xwriter.close();	
    		}
    		else {
    			response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR , "Failure deleting recipe"); // 500
    			return;
    		}  
    	}
    	catch (Exception ex) {
    		response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR , "Internal error occured: " + ex.getMessage()); // 500
    	}
    }
}
